package book;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import javax.microedition.io.Connector;
import javax.microedition.io.file.FileConnection;

import files.Files;

public class SpeedManagerImpl implements SpeedManager {
	private static final float TIME_SPENT_ON_CHARACTER = 1000 / 30;
	private static final int MIN_SPEED = 1;
	private static final int MAX_SPEED = 10;
	private static final int DEFAULT_SPEED = 4;

	private FileConnection fc;
	private InputStream fis;
	private OutputStream fos;

	private static final float TIME_RATIO_FACTOR = 1.5f;
	private float timeRatio = 1;
	private int speed;
	
	public SpeedManagerImpl() throws IOException {
		String speedFile = Files.getBookFolder() + "/Speed.txt";
		fc = (FileConnection) Connector.open(speedFile);

		if (!fc.exists()) {
			fc.create();
			fos = fc.openOutputStream();
			fos.write(Integer.toString(DEFAULT_SPEED).getBytes());
			fos.close();
		}
		readSpeedFromFile();
		applySpeed();
	}

	
	private void applySpeed() {
		for (int i = 0; i < Math.abs(speed - DEFAULT_SPEED); i++) {
			if (speed > DEFAULT_SPEED) {
				timeRatio = timeRatio / TIME_RATIO_FACTOR;
			} else {
				timeRatio = timeRatio * TIME_RATIO_FACTOR;
			}			
		}
	}


	private void readSpeedFromFile() throws IOException {
		byte[] b = new byte[20];
		fis = fc.openInputStream();
		int length = fis.read(b, 0, 20);
		fis.close();
		String raw = new String(b, 0, length);
		speed = Integer.parseInt(raw);
	}


	private int applyTimeRatio(int input) {
		return (int) (input * timeRatio);
	}

	public int computeDuration(String phrase) {
		int rawTimeSpent = (int) (phrase.length() * TIME_SPENT_ON_CHARACTER);
		return Math.max(applyTimeRatio(rawTimeSpent), applyTimeRatio(2500));
	}

	public void decreaseSpeed() {
		if (speed > MIN_SPEED) {
			timeRatio = timeRatio * TIME_RATIO_FACTOR;
			speed--;
			try {
				save();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

	public void increaseSpeed() {
		if (speed < MAX_SPEED) {
			timeRatio = timeRatio / TIME_RATIO_FACTOR;
			speed++;
			try {
				save();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
	
	public int getSpeed() {
		return speed;
	}


	private void save() throws IOException {
		fc.delete();
		fc.create();
		fos = fc.openOutputStream();
		fos.write(Integer.toString(speed).getBytes());
		fos.close();
	}
}
